package meiyunting.shiwuzhaoling.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 链路跟踪演示服务
 * 使用日志模拟链路跟踪
 */
@Slf4j
@Service
public class ZipkinDemoService {

    /**
     * 使用自定义Span执行业务逻辑
     * @param businessId 业务ID
     * @return 处理结果
     */
    public Map<String, Object> processWithCustomSpan(String businessId) {
        // 生成跟踪ID和Span ID
        String traceId = UUID.randomUUID().toString().replace("-", "");
        String spanId = UUID.randomUUID().toString().substring(0, 8);
        
        log.info("开始处理业务 [traceId={}, spanId={}, businessId={}]", traceId, spanId, businessId);
        
        try {
            // 记录事件
            log.info("业务处理开始 [traceId={}, spanId={}]", traceId, spanId);
            
            // 第一步处理
            log.info("执行第一步处理 [traceId={}, spanId={}]", traceId, spanId);
            sleep(100);
            
            // 记录事件
            log.info("第一步处理完成 [traceId={}, spanId={}]", traceId, spanId);
            
            // 第二步处理
            log.info("执行第二步处理 [traceId={}, spanId={}]", traceId, spanId);
            String step2SpanId = processStep2(businessId, traceId);
            
            // 第三步处理
            log.info("执行第三步处理 [traceId={}, spanId={}]", traceId, spanId);
            sleep(150);
            
            // 记录事件
            log.info("业务处理完成 [traceId={}, spanId={}]", traceId, spanId);
            
            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("businessId", businessId);
            result.put("status", "success");
            result.put("message", "业务处理成功");
            result.put("timestamp", System.currentTimeMillis());
            result.put("traceId", traceId);
            result.put("spanId", spanId);
            
            return result;
        } catch (Exception e) {
            // 记录异常
            log.error("业务处理异常 [traceId={}, spanId={}]", traceId, spanId, e);
            
            // 返回错误结果
            Map<String, Object> result = new HashMap<>();
            result.put("businessId", businessId);
            result.put("status", "error");
            result.put("message", "业务处理失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
            result.put("traceId", traceId);
            result.put("spanId", spanId);
            
            return result;
        } finally {
            log.info("业务处理结束 [traceId={}, spanId={}]", traceId, spanId);
        }
    }
    
    /**
     * 处理第二步，使用嵌套Span
     * @param businessId 业务ID
     * @param parentTraceId 父跟踪ID
     * @return 嵌套Span ID
     */
    private String processStep2(String businessId, String parentTraceId) {
        // 生成新的Span ID，保持相同的Trace ID
        String nestedSpanId = UUID.randomUUID().toString().substring(0, 8);
        
        log.info("第二步处理开始 [traceId={}, spanId={}, parentSpanId={}]", 
                parentTraceId, nestedSpanId, "子调用");
        
        try {
            // 模拟处理
            sleep(200);
            
            // 记录一些业务数据
            log.info("处理业务数据 [traceId={}, spanId={}, dataSize=1024]", 
                    parentTraceId, nestedSpanId);
            
            log.info("第二步处理完成 [traceId={}, spanId={}]", parentTraceId, nestedSpanId);
            
            return nestedSpanId;
        } finally {
            log.info("第二步处理结束 [traceId={}, spanId={}]", parentTraceId, nestedSpanId);
        }
    }
    
    /**
     * 模拟处理延时
     */
    private void sleep(long milliseconds) {
        try {
            TimeUnit.MILLISECONDS.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
} 